# Manipulating the DOM

# Selecting Elements

You have access to all of an element’s properties. You can modify

  • the contents of the element
  • attributes
  • properties

# .querySelector() and .querySelectorAll()

  • querySelector() only returns the first element that matches the specified CSS selectors.
  • To return all the matches, use the querySelectorAll() :
    • It returns a NodeList object, representing elements that match the specified CSS selector(s). Looks like an Array, but it's not
  • If no matches are found, null is returned.

Inside the brackets the same rules apply as with any CSS selectors:

  • # for IDs
  • .​ (dot) for classes
  • [ ] for attributes, etc.
// find and return the element with an ID of "header"
document.querySelector('#header');

// find and return the first element with the class "header"
document.querySelector('.header');

// find and return the first <header> element
document.querySelector('header');

Select by attribute:

<p aria-hidden="true">Lorem Ipsum ...</p>
document.querySelector("[aria-hidden]"); 
document.querySelector('[aria-hidden="true"]');

Select by Order:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
// Select Item 2 and Item 3
document.querySelector('li + li');

Multiple selectors:

<h1>Header</h1>
<h2>Sub Header</h2>
document.querySelector('h1, h2');

# Usage:

Apply this method on the whole DOM or on a selected part of the DOM.

// Get the first match:
document.querySelector() 
// Get all matches:
document.querySelectorAll()
// Match on children:
const navigation = document.querySelector("#nav") 
navigation.querySelector(‘li')

# Shorthands

# .getElementById()

Often the best way to select a single element.

const footer = document.getElementById('footer');

'footer', not '#footer'

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

Selecting Multiple Elements At Once:

Beware of the S: getElementsBy...

# .getElementsByClassName()

document.getElementsByClassName('brand-color');

https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

# .getElementsByTagName()

-> aktive Node-List: adapts, when the page-content changes and it is faster than:querySelectorAll() (static Node-List)

document.getElementsByTagName('p');

Also:document.getElementByTagName()


# Special Accessors

Every Node object has special accessors. These are properties of DOM elements and read-only.

  • element.childNodes - returns a collection of a node's child nodes, as a NodeList object
  • element.firstChild
  • element.lastChild
  • element.parentNode
  • element.closest('p') -Traverses all children of the parent in search for a match
  • .children - return a list of the element’s children and return null if the element has no children.
  • previousSibling/nextSibling

# An Element's (Text) Content

# .innerHTML

Each element has an .innerHTML property. This represents the markup of the element's content. We can use this to:

  • get an element's (and all of its descendants!) HTML content
  • set an element's HTML content

It retuns: it looks like a string. Technically, what it returns is called a DOMString.

  • https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

# .outerHTML

rarely used - Represents the HTML element itself, as well as its children.

<h1 id="pick-me">Greetings To <span>All</span>!</h1>

const innerResults = document.querySelector('#pick-me').innerHTML;
console.log(innerResults); // logs the string: "Greetings To <span>All</span>!"

const outerResults = document.querySelector('#pick-me').outerHTML;
console.log(outerResults); // logs the string: "<h1 id="pick-me">Greetings To <span>All</span>!</h1>"
  • https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML

# .textContent

The .textContent property will set and return the text content of an element and all its descendants

nanodegreeCard.textContent = "I will be the updated text!";

Passing any text that looks like HTML to the .textContent property will still be displayed as text. It will not be displayed as HTML when the element is rendered.

# .innerText

.innerText will get the visible text of the element.


# Creating new elements

# .createElement

The .createElement() method is a method on the document object. It just creates an an empty element with no inner HTML. It doesn't add it to the DOM.

In order add it to the web page, you must assign it to be the child of an element that already exists on the DOM. We call this process appending.appendChild()

const div = document.createElement('div')
div.innerHTML = '<p>Text</p>'
// or
div.innerText = 'Text'

# .createTextNode

Not recommendet: it's faster and easier to just update the element's text with the .textContent property.

var h = document.createElement("h1")
var t = document.createTextNode("Hello World");
h.appendChild(t);
const myPara = document.createElement('p');
const textOfParagraph = document.createTextNode('I am the text for the paragraph!');

myPara.appendChild(textOfParagraph);
document.body.appendChild(myPara);

the code below will provide the exact same result:

const myPara = document.createElement('p');

myPara.textContent = 'I am the text for the paragraph!';
document.body.appendChild(myPara);
  • https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode

# Adding and replacing nodes

# .appendChild() etc.

method Description
element.appendChild(newElement) nests a new element inside another element. - will move an element from its current position to the new position!- https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild
document.body.appendChild(newElement) nests a new element inside the body tag
document.insertBefore(newElement, referenceElement) puts a new element just before the other element
document.replaceChild(newElement, oldElement) replaces one element with another

# .insertAdjacentHTML()

To insert HTML text anywhere around an element. It needs to be called on a parent element with two arguments:

  • the location of the HTML
  • the HTML text that is going to be inserted

The first argument to this method will let us insert the new HTML in one of four different locations

  • beforebegin – inserts the HTML text as a previous sibling

  • afterbegin – inserts the HTML text as the first child

  • beforeend – inserts the HTML text as the last child

  • afterend – inserts the HTML text as a following sibling

  • <!-- beforebegin -->
    <p>
        <!-- afterbegin -->
        Existing text/HTML content
        <!-- beforeend -->
    </p>
    <!-- afterend -->
    

The second argument text parses the specified text as HTML and inserts the resulting nodes into the DOM tree at a specified position.

const mainHeading = document.querySelector('#main-heading');
const htmlTextToAdd = '<h2>Skydiving is fun!</h2>';

mainHeading.insertAdjacentHTML('afterend', htmlTextToAdd);

# Removing nodes

method Description
parent.remove(element) removes an element directly .remove() MDN (opens new window)
parent.removeChild(element) removes an element removeChild MDN (opens new window) - drawback to the .removeChild() method: it requires access to parent. Workaround: mainHeading.parentElement.removeChild(mainHeading);
element.innerHTML = '' empties an element - deletes all children as well as all listeners

# Style Page Content

# .style

Modifying an Element's Style Attribute

.style provides access to the inline style of that HTML tag.

  • Good for setting one style at a time, but not great for controlling multiple styles.

  • does not implement a hyphen such as background-color, but rather camel case notation backgroundColor. MDN reference page (opens new window)

let blueElement = document.querySelector('.blue');
blueElement.style.backgroundColor = 'blue';

chaining syntax would also work:

document.querySelector('.blue').style.fontFamily = 'Roboto';

# .style.cssText

**Adding Multiple Styles At Once **

use .style.cssText to set multiple CSS styles at once!

const mainHeading = document.querySelector('h1');

mainHeading.style.cssText = 'color: blue; background-color: orange; font-size: 3.5em';

write the CSS styles just as you would in a stylesheet; so you write font-size rather than fontSize.

  • https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/cssText

# .setAttribute()

Setting An Element's Attributes

Another way to set styles for an element is to use the .setAttribute() method:

const mainHeading = document.querySelector('h1');

mainHeading.setAttribute('style', 'color: blue; background-color: orange; font-size: 3.5em;');

not just for styling page elements. You can use this method to set any attribute for an element. If you want to give an element an ID, you can do that!:

const mainHeading = document.querySelector('h1');

// add an ID to the heading's sibling element
mainHeading.nextElementSibling.setAttribute('id', 'heading-sibling');

// use the newly added ID to access that element
document.querySelector('#heading-sibling').style.backgroundColor = 'red';
  • https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute

# Other Properties

# Change Attributes of an Element

-> eveything inide the tag

.attributes gives a list of all attributes

.getAttribute("href") returns the value of a single attribute

.setAttribute("href", "www.google.com") sets the attribute

hasAttribute()

removeAttribute()


# .hidden

Allows to hide the Element by assigning it as true or false:

document.getElementById('sign').hidden = true;

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/hidden


# Accessing an Element's Classes

# .classList

  • .classList is by far the most helpful property of the bunch,

  • helps to keep your CSS styling out of your JavaScript code.

  • Use the .classList property more than any other.

const listOfClasses = mainHeading.classList;

Returns a DOMTokenList (opens new window). Similar to an Array.

Has a number of properties. Some of the most popularly used ones are:

  • .add() - to add a class to the list
  • .remove() - to remove a class from the list
  • .toggle() - to add the class if it doesn't exists or remove it from the list if it does already exist
  • .contains() - returns a boolean based on if the class exists in the list or not
element.classList.add('cool-class', ‘second-class)
element.classList.remove('bad-class')
element.classList.contains('another-class')

# .className

  • returns a space-separated string of all of the element's classes.

  • This isn't the most ideal format, it makes it hard to add or remove individual classes. -> would have to it convert into array.

// store the list of classes in a variable
const listOfClasses = mainHeading.className;
mainHeading.className = "im-the-new-class";

The above code erases any classes that were originally in the element's class attribute and replaces it